
#include "string.h"
#include "eth_driver.h"
#include "mqtt.h"
#include "MQTTPacket.h"
#include "cjson.h"

MQTT_Config_t mqtt_config;
extern u8 SocketId;
//extern UINT8 SocketId;

//uint16_t desport = 1883;                           //MQTT server port
//uint16_t srcport = 4200;                           //source port

int pub_qos = 0;                                   //Publish quality of service
int sub_qos = 0;                                   //Subscription quality of service
char *username  = "gateway_mqtt";                         //Device name, unique for each device, available "/" for classification
char *password  = "gateway_mqtt";                         //Server login password
char *sub_topic = "topic/1";                       //subscribed session name
char *pub_topic = "topic/1";                       //Published session name
char *payload = "WCHNET MQTT";                     //Publish content

uint8_t con_flag  = 0;                             //Connect MQTT server flag
uint8_t pub_flag  = 0;                             //Publish session message flag/
uint8_t sub_flag  = 0;                             //Subscription session flag
uint8_t tout_flag = 0;                             //time-out flag
uint16_t packetid = 5;                             //package id
uint8_t publishValid = 0;
uint16_t timeCnt = 0;

//extern void mStopIfError(UINT8 iError);


void mqtt_init()
{
	strcpy(mqtt_config.user_name,"gateway_mqtt");
	strcpy(mqtt_config.passwd,"gateway_mqtt");
	mqtt_config.port = 1883;
	mqtt_config.is_connect = false;
	mqtt_config.IP[0] = 112;
	mqtt_config.IP[1] = 74;
	mqtt_config.IP[2] = 97;
	mqtt_config.IP[3] = 118;
	
	strcpy((char *)&mqtt_config.Subscribed_topic[0][0],"GATEWAY/SetData");
	strcpy((char *)&mqtt_config.Subscribed_topic[1][0],"GATEWAY/UpLoadData");
	strcpy((char *)&mqtt_config.Subscribed_topic[2][0],"topic/3");
	strcpy((char *)&mqtt_config.Subscribed_topic[3][0],"topic/4");

}
/*********************************************************************
 * @fn      Transport_Open
 *
 * @brief   open the TCP connection.
 *
 * @return  socket id
 */
uint8_t Transport_Open(void)
{
    uint8_t i;
    SOCK_INF TmpSocketInf;

    memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));
    memcpy((void *)TmpSocketInf.IPAddr,mqtt_config.IP,4);
    TmpSocketInf.DesPort = mqtt_config.port;
    TmpSocketInf.SourPort = 4200;
    TmpSocketInf.ProtoType = PROTO_TYPE_TCP;
    TmpSocketInf.RecvBufLen = RECE_BUF_LEN;
    i = WCHNET_SocketCreat(&SocketId,&TmpSocketInf);
    mStopIfError(i);

    i = WCHNET_SocketConnect(SocketId);
    mStopIfError(i);
    return SocketId;
}

/*********************************************************************
 * @fn      Transport_Close
 *
 * @brief   close the TCP connection.
 *
 * @return  @ERR_T
 */
uint8_t Transport_Close(void)
{
    uint8_t i;
    i = WCHNET_SocketClose(SocketId,TCP_CLOSE_NORMAL);
    mStopIfError(i);
    return i;
}

/*********************************************************************
 * @fn      Transport_SendPacket
 *
 * @brief   send data.
 *
 * @param   buf - data buff
 *          len - data length
 *
 * @return  none
 */
void Transport_SendPacket(uint8_t *buf, uint32_t len)
{
	WCHNET_SocketSend(SocketId, buf, &len);
	//printf("%d bytes uploaded!\r\n",len);
}

/*********************************************************************
 * @fn      MQTT_Connect
 *
 * @brief   Establish MQTT connection.
 *
 * @param   username - user name.
 *          password - password
 *
 * @return  none
 */
void MQTT_Connect(char *username, char *password)
{
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    uint32_t len;
    uint8_t buf[200];

    data.clientID.cstring = "admin1";
    data.keepAliveInterval = 2000;
    data.cleansession = 1;
    data.username.cstring = username;
    data.password.cstring = password;

    len = MQTTSerialize_connect(buf,sizeof(buf),&data);
    Transport_SendPacket(buf,len);
}

/*********************************************************************
 * @fn      MQTT_Subscribe
 *
 * @brief   MQTT subscribes to a topic.
 *
 * @param   topic - Topic name to subscribe to
 *          req_qos - quality of service
 *
 * @return  none
 */
void MQTT_Subscribe( char *topic,int req_qos)
{
    MQTTString topicString = MQTTString_initializer;
    uint32_t len;
    uint32_t msgid = 1;
    uint8_t buf[200];

    topicString.cstring = topic;
    len = MQTTSerialize_subscribe(buf,sizeof(buf),0,msgid,1,&topicString,&req_qos);
    Transport_SendPacket(buf,len);
}

/*********************************************************************
 * @fn      MQTT_Unsubscribe
 *
 * @brief   MQTT unsubscribe from a topic.
 *
 * @param   topic - Topic name to unsubscribe to.
 *
 * @return  none
 */
void MQTT_Unsubscribe(char *topic)
{
    MQTTString topicString = MQTTString_initializer;
    uint32_t len;
    uint32_t msgid = 1;
    uint8_t buf[200];

    topicString.cstring = topic;
    len = MQTTSerialize_unsubscribe(buf,sizeof(buf),0,msgid,1,&topicString);
    Transport_SendPacket(buf,len);
}

/*********************************************************************
 * @fn      MQTT_Publish
 *
 * @brief   MQTT publishes a topic.
 *
 * @param   topic - Published topic name.
 *          qos - quality of service
 *          payload - data buff
 *
 * @return  none
 */
void MQTT_Publish(char *topic, int qos, char *data,uint32_t data_len)
{
    MQTTString topicString = MQTTString_initializer;
    //uint32_t payloadlen;
    uint32_t len;
    uint8_t buf[512];

    topicString.cstring = topic;
    //payloadlen = strlen(payload);
    len = MQTTSerialize_publish(buf,sizeof(buf),0,qos,0,packetid++,topicString,(unsigned char*)data,data_len);
    Transport_SendPacket(buf,len);
}

/*********************************************************************
 * @fn      MQTT_Pingreq
 *
 * @brief   MQTT sends heartbeat packet
 *
 * @return  none
 */
void MQTT_Pingreq(void)
{
    uint32_t len;
    uint8_t buf[200];

    len = MQTTSerialize_pingreq(buf,sizeof(buf));
    Transport_SendPacket(buf,len);
}

/*********************************************************************
 * @fn      MQTT_Disconnect
 *
 * @brief   Disconnect the MQTT connection
 *
 * @return  none
 */
void MQTT_Disconnect(void)
{
    uint32_t len;
    uint8_t buf[50];
    len = MQTTSerialize_disconnect(buf,sizeof(buf));
    Transport_SendPacket(buf,len);
}

/*********************************************************************
 * @fn      msgDeal
 *
 * @brief   Dealing with subscription information.
 *
 * @param   msg - data buff
 *          len - data length
 *
 * @return  none
 */
void msgDeal(unsigned char *msg, int len)
{
    unsigned char *ptr = msg;
	uint8_t i;
	
    printf("payload len = %d\r\n",len);
    printf("payload: ");
    for( i = 0; i < len; i++)
    {
        printf("%c ",(uint16_t)*ptr);
        ptr++;
    }
    printf("\r\n");
}

void hex_to_str(char *hex, int len, char *str) {
    for (int i = 0; i < len; i += 2) {
        sprintf(str + i / 2, "%c", (unsigned char)strtol(hex + i, NULL, 16));
    }
}


// 将十六进制数组转换为字符串
char* hex_array_to_string(const unsigned char* hex_array, size_t array_size) {
    // 计算所需的字符串长度（每个十六进制数转换为两个字符，再加上结尾的空字符）
    size_t string_length = array_size * 2 + 1;
    
    // 分配足够的内存来存储字符串（加1是为了存储结尾的空字符）
    char* hex_string = (char*)malloc(string_length);
    if (hex_string == NULL) {
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }

    // 遍历十六进制数组，逐个转换为字符串
    for (size_t i = 0; i < array_size; ++i) {
        sprintf(hex_string + (i * 2), "%02x", hex_array[i]); // 每两个字符表示一个十六进制数
    }
    
    // 添加结尾的空字符
    hex_string[string_length - 1] = '\0';

    return hex_string;
}




void hexStringToByteArray(const char *hexString, unsigned char *byteArray, int byteArraySize) {
    int length = strlen(hexString);
    if (length % 2 != 0) {
        printf("Invalid hex string length.\n");
        return;
    }

    int byteIndex = 0;
    for (int i = 0; i < length; i += 2) {
        char byteString[3];
        byteString[0] = hexString[i];
        byteString[1] = hexString[i + 1];
        byteString[2] = '\0';

        byteArray[byteIndex++] = (unsigned char)strtol(byteString, NULL, 16);
        if (byteIndex >= byteArraySize) {
            break;
        }
    }
}


void MQTT_Send_Publish(uint8_t type ,uint8_t func_code,uint8_t *data_buffer,uint32_t len)
{
    uint8_t act_data[1024]={0};
    uint8_t buffer[1024]={0};


    // 转换为字符串
    char* hex_string = hex_array_to_string(data_buffer, len);
    //printf("Hex string: %s\n", hex_string);



    if(type == MQTT_DATA_VOICE_TYPE)
    {

        cJSON *root = cJSON_CreateObject();
        cJSON_AddStringToObject(root, "type", "AUDIO_TYPE");

        cJSON *data = cJSON_CreateObject();
        cJSON_AddNumberToObject(data, "audio_frame", func_code);
        hex_to_str((char *)data_buffer,len,(char*)buffer);
        //memcpy(act_data,data,len);
//        for(int i = 0;i<len;i++)
//            printf("%02x:",data_buffer[i]);
        //printf("hex_string %s\r\n",hex_string);

        cJSON_AddStringToObject(data, "audio_data", (char*)hex_string);

        cJSON_AddItemToObject(root, "data", data);

        char *json_str = cJSON_Print(root);
        //printf("%s", json_str);

        //printf("len =%d\r\n",strlen(json_str));
        MQTT_Publish((char *)&mqtt_config.Subscribed_topic[1][0],0,json_str,strlen(json_str));




        cJSON_Delete(root);
        free(json_str);

        
    // 释放动态分配的内存
    free(hex_string);


    }else if (type == MQTT_DATA_BUSINESS_TYPE) {

    }


}



extern void write_to_audio(uint8_t type,uint8_t *data,uint16_t len);







void MQTT_Recevice_callback(uint8_t *data_buffer,uint32_t len)
{
    uint8_t act_data[1024]={0};
    uint8_t buffer[1024]={0};


 // 解析JSON字符串
    cJSON *root = cJSON_Parse(data_buffer);
    if (root == NULL) {
        printf("Error parsing JSON: %s\n", cJSON_GetErrorPtr());
        return 1;
    }

    // 获取并打印"type"字段的值
    cJSON *type = cJSON_GetObjectItemCaseSensitive(root, "type");
    if (cJSON_IsString(type) && (type->valuestring != NULL)) {
        //printf("Type: %s\n", type->valuestring);
    } else {
        printf("Type field is missing or not a string.\n");
    }

    // 获取"data"字段的子对象
    cJSON *data = cJSON_GetObjectItemCaseSensitive(root, "data");
    if (cJSON_IsObject(data)) {
        // 获取并打印"audio_frame"字段的值
        cJSON *audioFrame = cJSON_GetObjectItemCaseSensitive(data, "audio_frame");
        if (cJSON_IsNumber(audioFrame)) {
            //printf("Audio Frame: %d\n", audioFrame->valueint);
        } else {
            printf("Audio Frame field is missing or not a number.\n");
        }

        // 获取并打印"audio_data"字段的值
        cJSON *audioData = cJSON_GetObjectItemCaseSensitive(data, "audio_data");
        if (cJSON_IsString(audioData) && (audioData->valuestring != NULL)) {
            //printf("Audio Data: %s\n", audioData->valuestring);


            int byteArraySize = strlen(audioData->valuestring)/2;
            unsigned char byteArray[byteArraySize];

            hexStringToByteArray(audioData->valuestring, byteArray, byteArraySize);

            write_to_audio(audioFrame->valueint,byteArray,byteArraySize);
            // printf("Hexadecimal String: %s,size %d\r\n", audioData->valuestring,byteArraySize);
            //                printf("Byte Array: ");
            //                for (int i = 0; i < byteArraySize; i++) {
            //                    printf("0x%02X", byteArray[i]);
            //                    if (i < byteArraySize - 1) {
            //                        printf(", ");
            //                    }
            //                }
            //                printf("\n");



        } else {
            printf("Audio Data field is missing or not a string.\n");
        }
    } else {
        printf("Data field is missing or not an object.\n");
    }

    // 释放内存
    cJSON_Delete(root);

//     // 转换为字符串
//     char* hex_string = hex_array_to_string(data_buffer, len);
//     //printf("Hex string: %s\n", hex_string);



//     if(type == MQTT_DATA_VOICE_TYPE)
//     {

//         cJSON *root = cJSON_CreateObject();
//         cJSON_AddStringToObject(root, "type", "AUDIO_TYPE");

//         cJSON *data = cJSON_CreateObject();
//         cJSON_AddNumberToObject(data, "audio_frame", func_code);
//         hex_to_str((char *)data_buffer,len,(char*)buffer);
//         //memcpy(act_data,data,len);
// //        for(int i = 0;i<len;i++)
// //            printf("%02x:",data_buffer[i]);
//         //printf("hex_string %s\r\n",hex_string);

//         cJSON_AddStringToObject(data, "audio_data", (char*)hex_string);

//         cJSON_AddItemToObject(root, "data", data);

//         char *json_str = cJSON_Print(root);
//         //printf("%s", json_str);

//         //printf("len =%d\r\n",strlen(json_str));
//         MQTT_Publish((char *)&mqtt_config.Subscribed_topic[0][0],0,json_str,strlen(json_str));




//         cJSON_Delete(root);
//         free(json_str);

        
//     // 释放动态分配的内存
//     free(hex_string);


//     }else if (type == MQTT_DATA_BUSINESS_TYPE) {

//     }


}
